package com.sojson.util.file.interfaces.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;

import com.sojson.constant.ConstantByMap;
import com.sojson.constant.IpConfig;
import com.sojson.util.StringUtil;
import com.sojson.util.file.FileUtil;
import com.sojson.util.file.interfaces.FileSystemInterface;
import com.sojson.util.id.GUIDUtil;

/**
 * FastDFS文件系统工具类
 * 
 * @author liu
 * @Date 2020-06-15 14:45:43
 * @Description
 *
 */
public class FileUtilImpl implements FileSystemInterface {

    private static FileUtilImpl fileUtilsImpl;

    private FileUtilImpl() {}

    /**
     * 将本地文件上传到服务器
     * 
     * @param filePath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public String upload(String filePath) throws Exception {
        return uploading(FileUtil.getFileName(filePath), filePath);
    }

    /**
     * 将本地文件上传到服务器
     * 
     * @param fileName 文件名
     * @param filePath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public String uploading(String fileName, String filePath) throws Exception {
        return upload("", fileName, filePath);
    }

    /**
     * 将本地文件上传到服务器
     * 
     * @param fileSuffix 文件后缀
     * @param filePath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public String uploadingBySuffix(String fileSuffix, String filePath) throws Exception {
        return uploading(new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString(), filePath);
    }

    /**
     * 将本地文件上传到服务器
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param filePath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public String upload(String bucketName, String filePath) throws Exception {
        return upload(bucketName, FileUtil.getFileName(filePath), filePath);
    }

    /**
     * 将本地文件上传到服务器
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param fileSuffix 文件后缀
     * @param filePath 本地文件路径
     * @return
     * @throws Exception
     */
    @Override
    public String uploading(String bucketName, String fileSuffix, String filePath) throws Exception {
        return upload(bucketName, new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString(), filePath);
    }

    /**
     * 将本地文件上传到服务器
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param fileName 文件名
     * @param filePath 本地文件路径
     * @return
     * @throws Exception
     */
    @Override
    public String upload(String bucketName, String fileName, String filePath) throws Exception {
        File bucketNameFile = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + bucketName);
        if (!bucketNameFile.exists()) {
            bucketNameFile.mkdirs();
        }
        String path = new StringBuilder(bucketName).append("/").append(fileName).toString();
        File file = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + path);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileUtil.copyFile(new File(filePath), file);
        return FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE_URL + path;
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param bytes 文件的字节流
     * @param fileSuffix 文件后缀
     * @return 
     * @throws Exception
     */
    @Override
    public String uploading(byte[] bytes, String fileSuffix) throws Exception {
        return upload(bytes, new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString());
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param bytes 文件的字节流
     * @param fileName 文件名
     * @return 
     * @throws Exception
     */
    @Override
    public String upload(byte[] bytes, String fileName) throws Exception {
        return upload(bytes, fileName, "");
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param bytes 文件的字节流
     * @param fileSuffix 文件后缀
     * @param bucketName 服务器文件路径(一级目录)
     * @return
     * @throws Exception
     */
    @Override
    public String uploading(byte[] bytes, String fileSuffix, String bucketName) throws Exception {
        return upload(bytes, new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString(), bucketName);
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param bytes 文件的字节流
     * @param fileName 文件名
     * @param bucketName 服务器文件路径(一级目录)
     * @return
     * @throws Exception
     */
    @Override
    public String upload(byte[] bytes, String fileName, String bucketName) throws Exception {
        FileOutputStream fileOutputStream = null;

        File bucketNameFile = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + bucketName);
        if (!bucketNameFile.exists()) {
            bucketNameFile.mkdirs();
        }
        String path = new StringBuilder(bucketName).append("/").append(fileName).toString();
        File file = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + path);
        if (!file.exists()) {
            file.createNewFile();
        }

        try {
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(bytes);
        } finally {
            FileUtil.closeStream(fileOutputStream);
        }

        return FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE_URL + path;
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param inputStream 文件的输入流
     * @param fileSuffix 文件后缀
     * @return 
     * @throws Exception
     */
    @Override
    public String uploading(InputStream inputStream, String fileSuffix) throws Exception {
        return upload(inputStream, new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString());
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param inputStream 文件的输入流
     * @param fileName 文件名
     * @return 
     * @throws Exception
     */
    @Override
    public String upload(InputStream inputStream, String fileName) throws Exception {
        return upload(inputStream, fileName, "");
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param inputStream 文件的输入流
     * @param fileSuffix 文件后缀
     * @param bucketName 服务器文件路径(一级目录)
     * @return
     * @throws Exception
     */
    @Override
    public String uploading(InputStream inputStream, String fileSuffix, String bucketName) throws Exception {
        return upload(inputStream, new StringBuilder(GUIDUtil.generateGuid()).append(fileSuffix).toString(),
            bucketName);
    }

    /**
     * 将文件流上传到服务器
     * 
     * @param inputStream 文件的输入流
     * @param fileName 文件名
     * @param bucketName 服务器文件路径(一级目录)
     * @return
     * @throws Exception
     */
    @Override
    public String upload(InputStream inputStream, String fileName, String bucketName) throws Exception {
        FileOutputStream fileOutputStream = null;

        File bucketNameFile = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + bucketName);
        if (!bucketNameFile.exists()) {
            bucketNameFile.mkdirs();
        }
        String path = new StringBuilder(bucketName).append("/").append(fileName).toString();
        File file = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + path);
        if (!file.exists()) {
            file.createNewFile();
        }

        try {
            fileOutputStream = new FileOutputStream(file);
            IOUtils.copy(inputStream, fileOutputStream);
            fileOutputStream.flush();
        } finally {
            FileUtil.closeStream(inputStream, fileOutputStream);
        }

        return FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE_URL + path;
    }

    /**
     * 根据Key删除文件
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 成功还是失败(true:成功,false:失败)
     * @throws Exception
     */
    @Override
    public boolean remove(String key) throws Exception {
        return remove(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key);
    }

    /**
     * 根据Key删除文件
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 成功还是失败(true:成功,false:失败)
     * @throws Exception
     */
    @Override
    public boolean remove(String bucketName, String key) throws Exception {
        File file = new File(new StringBuilder(bucketName).append(key).toString());
        if (file.exists()) {
            return file.delete();
        }
        return true;
    }

    /**
     * 从服务器下载文件到本地
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 
     * @throws Exception
     */
    @Override
    public boolean download(String key) throws Exception {
        return true;
    }

    /**
     * 从服务器下载文件到本地
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 
     * @throws Exception
     */
    @Override
    public boolean downloading(String bucketName, String key) throws Exception {
        return download(bucketName, key, FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE);
    }

    /**
     * 从服务器下载文件到本地
     * 
     * @param key 密钥(上传后返回的字符串)
     * @param targetPath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public boolean download(String key, String targetPath) throws Exception {
        return download(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key, targetPath);
    }

    /**
     * 从服务器下载文件到本地
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @param targetPath 本地文件路径
     * @return 
     * @throws Exception
     */
    @Override
    public boolean download(String bucketName, String key, String targetPath) throws Exception {
        File resourceFile = new File(new StringBuilder(bucketName).append(key).toString());

        int indexOf = key.lastIndexOf("/");
        if (indexOf > 0) {
            key = key.substring(indexOf);
        }
        File bucketNameFile = new File(targetPath);
        if (!bucketNameFile.exists()) {
            bucketNameFile.mkdirs();
        }
        File file = new File(new StringBuilder(targetPath).append(key).toString());
        if (!file.exists()) {
            file.createNewFile();
        }
        FileUtil.copyFile(resourceFile, file);
        return true;
    }

    /**
     * 根据Key获取文件流
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 文件字节流
     * @throws Exception
     */
    @Override
    public byte[] downloadGetBytes(String key) throws Exception {
        return downloadGetBytes(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key);
    }

    /**
     * 根据Key获取文件流
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 文件字节流
     * @throws Exception
     */
    @Override
    public byte[] downloadGetBytes(String bucketName, String key) throws Exception {
        InputStream downloadGetInputStream = null;
        byte[] bytes = null;

        try {
            downloadGetInputStream = downloadGetInputStream(bucketName, key);
            bytes = IOUtils.toByteArray(downloadGetInputStream);
        } finally {
            FileUtil.closeStream(downloadGetInputStream);
        }

        return bytes;
    }

    /**
     * 根据Key获取文件流
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 
     * @throws Exception
     */
    @Override
    public InputStream downloadGetInputStream(String key) throws Exception {
        return downloadGetInputStream(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key);
    }

    /**
     * 根据Key获取文件流
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 
     * @throws Exception
     */
    @Override
    public InputStream downloadGetInputStream(String bucketName, String key) throws Exception {
        return new FileInputStream(new File(new StringBuilder(bucketName).append(key).toString()));
    }

    /**
     * 根据Key获取Url
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 得到的Url
     */
    @Override
    public String getUrl(String key) {
        return IpConfig.url + key;
    }

    /**
     * 根据Key获取Url
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 得到的Url
     */
    @Override
    public String getUrl(String bucketName, String key) {
        return IpConfig.url + key;
    }

    /**
     * 根据Key获取Url(临时路径)
     * 
     * @param key 密钥(上传后返回的字符串)
     * @return 得到的Url
     */
    @Override
    public String getUrlTemporary(String key) {
        return getUrlTemporary(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key, ConstantByMap.FILE_URL_TIMEOUT);
    }

    /**
     * 根据Key获取Url(临时路径)
     * 
     * @param key 密钥(上传后返回的字符串)
     * @param timeout 地址超时时间(单位: 毫秒)
     * @return 得到的Url
     */
    @Override
    public String getUrlTemporary(String key, long timeout) {
        return getUrlTemporary(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE, key, timeout);
    }

    /**
     * 根据Key获取Url(临时路径)
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @return 得到的Url
     */
    @Override
    public String getUrlTemporary(String bucketName, String key) {
        return getUrlTemporary(bucketName, key, ConstantByMap.FILE_URL_TIMEOUT);
    }

    /**
     * 根据Key获取Url(临时路径)
     * 
     * @param bucketName 服务器文件路径(一级目录)
     * @param key 密钥(上传后返回的字符串)
     * @param timeout 地址超时时间(单位: 毫秒)
     * @return 得到的Url
     */
    @Override
    public String getUrlTemporary(String bucketName, String key, long timeout) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 判断一个对象是否是空(空对象)
     * 
     * @param obj
     * @return
     */
    public static boolean isBlankObject(Object obj) {
        return StringUtil.isBlankObject(obj);
    }

    public static FileUtilImpl getInstances() {
        if (isBlankObject(fileUtilsImpl)) {
            fileUtilsImpl = new FileUtilImpl();
        }
        return fileUtilsImpl;
    }

}